/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package univalle.eisc.pais.ai.searcheslab.view;

import java.awt.Cursor;
import java.awt.Frame;
import java.io.File;
import java.io.PrintStream;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import univalle.eisc.pais.ai.searcheslab.logic.Seeker;
import univalle.eisc.pais.ai.searcheslab.model.*;

/**
 *
 * @author victor
 */
public class MainWindowView extends javax.swing.JFrame {

    /**
     * Creates new form
     */
    public MainWindowView() {
        initComponents();
        changeDefaultStreamOutput();
        
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jFileChooser = new javax.swing.JFileChooser();
        jButtonLoadConfig = new javax.swing.JButton();
        jPanelStage = new javax.swing.JPanel();
        jPanelConfig = new javax.swing.JPanel();
        jLabelTitle = new javax.swing.JLabel();
        jLabelSearchType = new javax.swing.JLabel();
        jComboSearchType = new javax.swing.JComboBox();
        jLabelAlgorithm = new javax.swing.JLabel();
        jComboAlgorithm = new javax.swing.JComboBox();
        jButtonRun = new javax.swing.JButton();
        jLabelOutPut = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTextPaneOutPut = new javax.swing.JTextPane();
        jButtonClean = new javax.swing.JButton();
        JTextFilePath = new javax.swing.JTextField();
        jButtonChangeFile = new javax.swing.JButton();

        jButtonLoadConfig.setText("Cargar...");
        jButtonLoadConfig.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonLoadConfigActionPerformed(evt);
            }
        });

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Robot de Búsquedas");
        setExtendedState(Frame.MAXIMIZED_BOTH);

        jPanelStage.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0), 2, true));
        jPanelStage.setLayout(new java.awt.BorderLayout());

        jPanelConfig.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0), 2, true));

        jLabelTitle.setText("Configuración");

        jLabelSearchType.setText("Tipo de Búsqueda");

        jComboSearchType.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "No Informada", "Informada" }));
        jComboSearchType.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                jComboSearchTypeItemStateChanged(evt);
            }
        });

        jLabelAlgorithm.setText("Algoritmo");

        jComboAlgorithm.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Amplitud", "Costo Uniforme", "Profundidad" }));

        jButtonRun.setText("<< Procesar >>");
        jButtonRun.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonRunActionPerformed(evt);
            }
        });

        jLabelOutPut.setText("Salida");

        jTextPaneOutPut.setEditable(false);
        jScrollPane1.setViewportView(jTextPaneOutPut);

        jButtonClean.setText("Limpiar");
        jButtonClean.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonCleanActionPerformed(evt);
            }
        });

        JTextFilePath.setEditable(false);

        jButtonChangeFile.setText("...");
        jButtonChangeFile.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonChangeFileActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanelConfigLayout = new javax.swing.GroupLayout(jPanelConfig);
        jPanelConfig.setLayout(jPanelConfigLayout);
        jPanelConfigLayout.setHorizontalGroup(
            jPanelConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelConfigLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanelConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 189, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(jPanelConfigLayout.createSequentialGroup()
                        .addGroup(jPanelConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addComponent(JTextFilePath, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
                            .addComponent(jLabelTitle, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 189, Short.MAX_VALUE)
                            .addComponent(jComboSearchType, javax.swing.GroupLayout.Alignment.LEADING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jComboAlgorithm, javax.swing.GroupLayout.Alignment.LEADING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jButtonRun, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jButtonClean, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jLabelAlgorithm, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jLabelOutPut, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jLabelSearchType, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jButtonChangeFile, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addGap(0, 0, Short.MAX_VALUE)))
                .addContainerGap())
        );

        jPanelConfigLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {JTextFilePath, jButtonChangeFile, jButtonClean, jButtonRun, jComboAlgorithm, jComboSearchType, jLabelAlgorithm, jLabelOutPut, jLabelSearchType, jLabelTitle, jScrollPane1});

        jPanelConfigLayout.setVerticalGroup(
            jPanelConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelConfigLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabelTitle)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(JTextFilePath, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButtonChangeFile)
                .addGap(32, 32, 32)
                .addComponent(jLabelSearchType)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jComboSearchType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(12, 12, 12)
                .addComponent(jLabelAlgorithm)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jComboAlgorithm, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButtonRun)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jLabelOutPut)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 321, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButtonClean)
                .addContainerGap())
        );

        jPanelConfigLayout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {JTextFilePath, jButtonChangeFile});

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanelStage, javax.swing.GroupLayout.DEFAULT_SIZE, 863, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanelConfig, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jPanelConfig, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanelStage, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jButtonChangeFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonChangeFileActionPerformed

        if (jFileChooser.showOpenDialog(this)
                == JFileChooser.APPROVE_OPTION) {
            JTextFilePath.setText(jFileChooser.getSelectedFile().getAbsolutePath());
        }
        jButtonLoadConfigActionPerformed(evt);
    }//GEN-LAST:event_jButtonChangeFileActionPerformed

    private void jButtonLoadConfigActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonLoadConfigActionPerformed

        if (!JTextFilePath.getText().isEmpty()) {
            Config config = new Config();
            try {
                config.loadConfig(new File(JTextFilePath.getText()));
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(this, ex.getMessage(),
                        "Error", JOptionPane.ERROR_MESSAGE);
                config = null;
            }
            if (config != null) {
                initScene(config);
            }
        }


    }//GEN-LAST:event_jButtonLoadConfigActionPerformed

    private void jComboSearchTypeItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_jComboSearchTypeItemStateChanged

        if (jComboSearchType.getSelectedIndex() == 0) {
            jComboAlgorithm.setModel(
                    new DefaultComboBoxModel(
                    new Object[]{"Amplitud", "Costo Uniforme", "Profundidad"}));
        } else {
            jComboAlgorithm.setModel(
                    new DefaultComboBoxModel(
                    new Object[]{"Avara", "A*"}));
        }
    }//GEN-LAST:event_jComboSearchTypeItemStateChanged

    private void jButtonCleanActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonCleanActionPerformed
        jTextPaneOutPut.setText("");
    }//GEN-LAST:event_jButtonCleanActionPerformed

    private void jButtonRunActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonRunActionPerformed
        if (scene != null) {
            this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
            Seeker seeker = new Seeker();
            Route route = null;
            if (needReload) {
                scene.getStage().reload();
                needReload = false;
            }
            System.out.println("============================");
            switch (jComboSearchType.getSelectedIndex()) {
                case 0:
                    switch (jComboAlgorithm.getSelectedIndex()) {
                        case 0:
                            route = seeker.breadth(scene.getStage());
                            break;
                        case 1:
                            route = seeker.uniformCost(scene.getStage());
                            break;
                        case 2:
                            route = seeker.depth(scene.getStage());
                            break;
                        default:
                            ;
                    }
                    break;
                case 1:
                    switch (jComboSearchType.getSelectedIndex()) {
                        case 0:
                            route = seeker.greedy(scene.getStage());
                            break;
                        case 1:
                            route = seeker.aStar(scene.getStage());
                            break;
                        default:
                            ;
                    }
                    break;
                default:
                    ;
            }
            needReload = true;
            this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
            paintRoute(route);
        } else {
            JOptionPane.showMessageDialog(this, "Primero debe cargar un ambiente");
            jButtonChangeFileActionPerformed(evt);
        }
    }//GEN-LAST:event_jButtonRunActionPerformed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTextField JTextFilePath;
    private javax.swing.JButton jButtonChangeFile;
    private javax.swing.JButton jButtonClean;
    private javax.swing.JButton jButtonLoadConfig;
    private javax.swing.JButton jButtonRun;
    private javax.swing.JComboBox jComboAlgorithm;
    private javax.swing.JComboBox jComboSearchType;
    private javax.swing.JFileChooser jFileChooser;
    private javax.swing.JLabel jLabelAlgorithm;
    private javax.swing.JLabel jLabelOutPut;
    private javax.swing.JLabel jLabelSearchType;
    private javax.swing.JLabel jLabelTitle;
    private javax.swing.JPanel jPanelConfig;
    private javax.swing.JPanel jPanelStage;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextPane jTextPaneOutPut;
    // End of variables declaration//GEN-END:variables

    private void initScene(Config conf) {
        scene = new SceneView();
        scene.setStage(new Stage(conf));
        jPanelStage.removeAll();
        jPanelStage.add(scene);
        scene.repaint();
        scene.revalidate();
    }

    private void paintRoute(Route route) {

        final Stack<Node> nodes = route.getSteps();
        final Robot robot = scene.getStage().getRobot();
        final Item item1 = scene.getStage().getItem1();
        final Item item2 = scene.getStage().getItem2();
        final Place place1 = scene.getStage().getPlace1();
        final Place place2 = scene.getStage().getPlace2();

        Thread animation = new Thread(new Runnable() {

            @Override
            public void run() {
                for (int i = nodes.size() - 1; i >= 0; i--) {
                    Node node = nodes.get(i);
                    if (robot.getX() == item1.getX() && robot.getY() == item1.getY()) {
                        if (place1.getX() != item1.getX() || place1.getY() != item1.getY()) {
                            item1.setX(node.x);
                            item1.setY(node.y);
                        }
                    }
                    if (robot.getX() == item2.getX() && robot.getY() == item2.getY()) {
                        if (place2.getX() != item2.getX() || place2.getY() != item2.getY()) {
                            item2.setX(node.x);
                            item2.setY(node.y);
                        }
                    }
                    robot.setX(node.x);
                    robot.setY(node.y);

                    scene.repaint();
                    scene.revalidate();

                    try {
                        Thread.currentThread().sleep(500);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(MainWindowView.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        });
        animation.start();
    }
    private SceneView scene;
    private boolean needReload = false;

    private void changeDefaultStreamOutput() {
        JTextPaneOutputStream jtpos = new JTextPaneOutputStream(jTextPaneOutPut);
        System.setOut(new PrintStream(jtpos));
        System.setErr(new PrintStream(jtpos));
    }
}
